home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / sys5 / iscwmpst.z / iscwmpst / tcp / src / lapb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-02  |  39.3 KB  |  1,608 lines

  1. /* @(#) $Header: lapb.c,v 1.18 91/06/01 22:18:18 deyke Exp $ */
  2.  
  3. /* Link Access Procedures Balanced (LAPB), the upper sublayer of
  4.  * AX.25 Level 2.
  5.  */
  6. #include <time.h>
  7. #include "global.h"
  8. #include "mbuf.h"
  9. #include "timer.h"
  10. #include "ax25.h"
  11. #include "lapb.h"
  12. #include "netrom.h"
  13. #include "asy.h"
  14. #include "cmdparse.h"
  15. #include "netuser.h"
  16.  
  17. extern struct ax25_cb *netrom_server_axcb;
  18.  
  19. char  *ax25states[] = {
  20.   "Disconnected",
  21.   "Conn pending",
  22.   "Connected",
  23.   "Disc pending"
  24. };
  25.  
  26. char  *ax25reasons[] = {
  27.   "Normal",
  28.   "Reset",
  29.   "Timeout",
  30.   "Network"
  31. };
  32.  
  33. int  ax_maxframe =      7;      /* Transmit flow control level */
  34. int  ax_paclen   =    236;      /* Maximum outbound packet size */
  35. int  ax_pthresh  =     64;      /* Send polls for packets larger than this */
  36. int  ax_retry    =     10;      /* Retry limit */
  37. int32 ax_t1init  =   5000;      /* Retransmission timeout */
  38. int32 ax_t2init  =   2000;      /* Acknowledgement delay timeout */
  39. int32 ax_t3init  = 900000;      /* No-activity timeout */
  40. int32 ax_t4init  =  60000;      /* Busy timeout */
  41. int32 ax_t5init  =   1000;      /* Packet assembly timeout */
  42. int  ax_window   =   2048;      /* Local flow control limit */
  43. struct ax25_cb *axcb_server;    /* Server control block */
  44.  
  45. static struct ax25_cb *axcb_head;
  46.  
  47. static void reset_t1 __ARGS((struct ax25_cb *cp));
  48. static void inc_t1 __ARGS((struct ax25_cb *cp));
  49. static void send_packet __ARGS((struct ax25_cb *cp, int type, int cmdrsp, struct mbuf *data));
  50. static int busy __ARGS((struct ax25_cb *cp));
  51. static void send_ack __ARGS((struct ax25_cb *cp, int cmdrsp));
  52. static void try_send __ARGS((struct ax25_cb *cp, int fill_sndq));
  53. static void setaxstate __ARGS((struct ax25_cb *cp, int newstate));
  54. static void t1_timeout __ARGS((struct ax25_cb *cp));
  55. static void t2_timeout __ARGS((struct ax25_cb *cp));
  56. static void t3_timeout __ARGS((struct ax25_cb *cp));
  57. static void t4_timeout __ARGS((struct ax25_cb *cp));
  58. static void t5_timeout __ARGS((struct ax25_cb *cp));
  59. static struct ax25_cb *create_axcb __ARGS((struct ax25_cb *prototype));
  60. static void build_path __ARGS((struct ax25_cb *cp, struct iface *ifp, struct ax25 *hdr, int reverse));
  61. static int put_reseq __ARGS((struct ax25_cb *cp, struct mbuf *bp, int ns));
  62. static int dodigipeat __ARGS((int argc, char *argv [], void *p));
  63. static int domaxframe __ARGS((int argc, char *argv [], void *p));
  64. static int domycall __ARGS((int argc, char *argv [], void *p));
  65. static int dopaclen __ARGS((int argc, char *argv [], void *p));
  66. static int dopthresh __ARGS((int argc, char *argv [], void *p));
  67. static int doaxreset __ARGS((int argc, char *argv [], void *p));
  68. static int doretry __ARGS((int argc, char *argv [], void *p));
  69. static int dorouteadd __ARGS((int argc, char *argv [], void *p));
  70. static void doroutelistentry __ARGS((struct ax_route *rp));
  71. static int doroutelist __ARGS((int argc, char *argv [], void *p));
  72. static int doroutestat __ARGS((int argc, char *argv [], void *p));
  73. static int doaxroute __ARGS((int argc, char *argv [], void *p));
  74. static int doaxstatus __ARGS((int argc, char *argv [], void *p));
  75. static int dot1 __ARGS((int argc, char *argv [], void *p));
  76. static int dot2 __ARGS((int argc, char *argv [], void *p));
  77. static int dot3 __ARGS((int argc, char *argv [], void *p));
  78. static int dot4 __ARGS((int argc, char *argv [], void *p));
  79. static int dot5 __ARGS((int argc, char *argv [], void *p));
  80. static int doaxwindow __ARGS((int argc, char *argv [], void *p));
  81.  
  82. /*---------------------------------------------------------------------------*/
  83.  
  84. static void reset_t1(cp)
  85. struct ax25_cb *cp;
  86. {
  87.   int32 tmp;
  88.  
  89.   tmp = cp->srtt + 2 * cp->mdev;
  90.   set_timer(&cp->timer_t1, tmp > 0 ? tmp : 1);
  91. }
  92.  
  93. /*---------------------------------------------------------------------------*/
  94.  
  95. static void inc_t1(cp)
  96. struct ax25_cb *cp;
  97. {
  98.   int32 tmp;
  99.  
  100.   tmp = (dur_timer(&cp->timer_t1) * 5 + 2) / 4;
  101.   if (tmp > 10 * cp->srtt) tmp = 10 * cp->srtt;
  102.   set_timer(&cp->timer_t1, tmp > 0 ? tmp : 1);
  103. }
  104.  
  105. /*---------------------------------------------------------------------------*/
  106.  
  107. #define next_seq(n)  (((n) + 1) & 7)
  108.  
  109. /*---------------------------------------------------------------------------*/
  110.  
  111. static void send_packet(cp, type, cmdrsp, data)
  112. struct ax25_cb *cp;
  113. int  type;
  114. int  cmdrsp;
  115. struct mbuf *data;
  116. {
  117.  
  118.   int  control;
  119.   struct mbuf *bp;
  120.  
  121.   if (cp->mode == STREAM && (type == I || type == UI)) {
  122.     if (!(bp = pushdown(data, 1))) {
  123.       free_p(data);
  124.       return;
  125.     }
  126.     *bp->data = PID_NO_L3;
  127.     data = bp;
  128.   }
  129.  
  130.   control = type;
  131.   if (type == I) {
  132.     control |= (cp->vs << 1);
  133.     cp->vs = next_seq(cp->vs);
  134.   }
  135.   if ((type & 3) != U) {
  136.     control |= (cp->vr << 5);
  137.     stop_timer(&cp->timer_t2);
  138.   }
  139.   if (cmdrsp & PF) control |= PF;
  140.   if (!(bp = pushdown(data, 1))) {
  141.     free_p(data);
  142.     return;
  143.   }
  144.   *bp->data = control;
  145.   data = bp;
  146.  
  147.   if (cmdrsp & DST_C)
  148.     cp->hdr.cmdrsp = LAPB_COMMAND;
  149.   else if (cmdrsp & SRC_C)
  150.     cp->hdr.cmdrsp = LAPB_RESPONSE;
  151.   else
  152.     cp->hdr.cmdrsp = VERS1;
  153.   if (!(bp = htonax25(&cp->hdr, data))) {
  154.     free_p(data);
  155.     return;
  156.   }
  157.   data = bp;
  158.  
  159.   if (type == RR || type == REJ || type == UA) cp->rnrsent = 0;
  160.   if (type == RNR) cp->rnrsent = 1;
  161.   if (type == REJ) cp->rejsent = 1;
  162.   if (cmdrsp == POLL) cp->polling = 1;
  163.   if (type == I || cmdrsp == POLL) start_timer(&cp->timer_t1);
  164.  
  165.   axroute(cp, data);
  166. }
  167.  
  168. /*---------------------------------------------------------------------------*/
  169.  
  170. static int  busy(cp)
  171. struct ax25_cb *cp;
  172. {
  173.   return cp->peer ? space_ax(cp->peer) <= 0 : cp->rcvcnt >= ax_window;
  174. }
  175.  
  176. /*---------------------------------------------------------------------------*/
  177.  
  178. static void send_ack(cp, cmdrsp)
  179. struct ax25_cb *cp;
  180. int  cmdrsp;
  181. {
  182.   if (busy(cp))
  183.     send_packet(cp, RNR, cmdrsp, NULLBUF);
  184.   else if (!cp->rejsent && (cp->reseq[0].bp || cp->reseq[1].bp ||
  185.                 cp->reseq[2].bp || cp->reseq[3].bp ||
  186.                 cp->reseq[4].bp || cp->reseq[5].bp ||
  187.                 cp->reseq[6].bp || cp->reseq[7].bp))
  188.     send_packet(cp, REJ, cmdrsp, NULLBUF);
  189.   else
  190.     send_packet(cp, RR, cmdrsp, NULLBUF);
  191. }
  192.  
  193. /*---------------------------------------------------------------------------*/
  194.  
  195. static void try_send(cp, fill_sndq)
  196. struct ax25_cb *cp;
  197. int  fill_sndq;
  198. {
  199.  
  200.   int  cnt;
  201.   struct mbuf *bp;
  202.  
  203.   stop_timer(&cp->timer_t5);
  204.   while (cp->unack < cp->cwind) {
  205.     if (cp->state != CONNECTED || cp->remote_busy) return;
  206.     if (fill_sndq && cp->t_upcall) {
  207.       cnt = space_ax(cp);
  208.       if (cnt > 0) {
  209.     (*cp->t_upcall)(cp, cnt);
  210.     if (cp->unack >= cp->cwind) return;
  211.       }
  212.     }
  213.     if (!cp->sndq) return;
  214.     if (cp->mode == STREAM) {
  215.       cnt = len_p(cp->sndq);
  216.       if (cnt < ax_paclen) {
  217.     if (cp->unack) return;
  218.     if (!cp->peer && cp->sndqtime + ax_t5init - msclock() > 0) {
  219.       set_timer(&cp->timer_t5, cp->sndqtime + ax_t5init - msclock());
  220.       start_timer(&cp->timer_t5);
  221.       return;
  222.     }
  223.       }
  224.       if (cnt > ax_paclen) cnt = ax_paclen;
  225.       if (!(bp = alloc_mbuf(cnt))) return;
  226.       pullup(&cp->sndq, bp->data, bp->cnt = cnt);
  227.     } else {
  228.       bp = dequeue(&cp->sndq);
  229.     }
  230.     enqueue(&cp->resndq, bp);
  231.     cp->unack++;
  232.     cp->sndtime[cp->vs] = msclock();
  233.     dup_p(&bp, bp, 0, MAXINT16);
  234.     send_packet(cp, I, CMD, bp);
  235.   }
  236. }
  237.  
  238. /*---------------------------------------------------------------------------*/
  239.  
  240. static void setaxstate(cp, newstate)
  241. struct ax25_cb *cp;
  242. int  newstate;
  243. {
  244.   int  oldstate;
  245.  
  246.   oldstate = cp->state;
  247.   cp->state = newstate;
  248.   cp->polling = 0;
  249.   cp->retry = 0;
  250.   stop_timer(&cp->timer_t1);
  251.   stop_timer(&cp->timer_t2);
  252.   stop_timer(&cp->timer_t4);
  253.   stop_timer(&cp->timer_t5);
  254.   reset_t1(cp);
  255.   switch (newstate) {
  256.   case DISCONNECTED:
  257.     if (cp->peer) close_ax(cp->peer);
  258.     if (cp->s_upcall) (*cp->s_upcall)(cp, oldstate, newstate);
  259.     if (cp->peer && cp->peer->state == DISCONNECTED) {
  260.       del_ax(cp->peer);
  261.       del_ax(cp);
  262.     }
  263.     break;
  264.   case CONNECTING:
  265.     if (cp->s_upcall) (*cp->s_upcall)(cp, oldstate, newstate);
  266.     send_packet(cp, SABM, POLL, NULLBUF);
  267.     break;
  268.   case CONNECTED:
  269.     if (cp->peer && cp->peer->state == DISCONNECTED) {
  270.       send_packet(cp->peer, UA, FINAL, NULLBUF);
  271.       setaxstate(cp->peer, CONNECTED);
  272.     }
  273.     if (cp->s_upcall) (*cp->s_upcall)(cp, oldstate, newstate);
  274.     try_send(cp, 1);
  275.     break;
  276.   case DISCONNECTING:
  277.     if (cp->peer) close_ax(cp->peer);
  278.     if (cp->s_upcall) (*cp->s_upcall)(cp, oldstate, newstate);
  279.     send_packet(cp, DISC, POLL, NULLBUF);
  280.     break;
  281.   }
  282. }
  283.  
  284. /*---------------------------------------------------------------------------*/
  285.  
  286. static void t1_timeout(cp)
  287. struct ax25_cb *cp;
  288. {
  289.   inc_t1(cp);
  290.   /* cp->cwind = 1; OLE */
  291.   if (++cp->retry > ax_retry) cp->reason = TIMEOUT;
  292.   switch (cp->state) {
  293.   case DISCONNECTED:
  294.     break;
  295.   case CONNECTING:
  296.     if (cp->peer && cp->peer->state == DISCONNECTED)
  297.       if (cp->retry > 2)
  298.     setaxstate(cp, DISCONNECTED);
  299.       else
  300.     start_timer(&cp->timer_t1);
  301.     else if (cp->retry > ax_retry)
  302.       setaxstate(cp, DISCONNECTED);
  303.     else
  304.       send_packet(cp, SABM, POLL, NULLBUF);
  305.     break;
  306.   case CONNECTED:
  307.     if (cp->retry > ax_retry) {
  308.       setaxstate(cp, DISCONNECTING);
  309.     } else if (!cp->polling && !cp->remote_busy && cp->unack &&
  310.            len_p(cp->resndq) <= ax_pthresh) {
  311.       int  old_vs;
  312.       struct mbuf *bp;
  313.       old_vs = cp->vs;
  314.       cp->vs = (cp->vs - cp->unack) & 7;
  315.       cp->sndtime[cp->vs] = 0;
  316.       dup_p(&bp, cp->resndq, 0, MAXINT16);
  317.       send_packet(cp, I, POLL, bp);
  318.       cp->vs = old_vs;
  319.     } else {
  320.       send_ack(cp, POLL);
  321.     }
  322.     break;
  323.   case DISCONNECTING:
  324.     if (cp->retry > ax_retry)
  325.       setaxstate(cp, DISCONNECTED);
  326.     else
  327.       send_packet(cp, DISC, POLL, NULLBUF);
  328.     break;
  329.   }
  330. }
  331.  
  332. /*---------------------------------------------------------------------------*/
  333.  
  334. static void t2_timeout(cp)
  335. struct ax25_cb *cp;
  336. {
  337.   send_ack(cp, RESP);
  338. }
  339.  
  340. /*---------------------------------------------------------------------------*/
  341.  
  342. static void t3_timeout(cp)
  343. struct ax25_cb *cp;
  344. {
  345.   if (!run_timer(&cp->timer_t1)) send_ack(cp, POLL);
  346. }
  347.  
  348. /*---------------------------------------------------------------------------*/
  349.  
  350. static void t4_timeout(cp)
  351. struct ax25_cb *cp;
  352. {
  353.   if (!cp->polling) send_ack(cp, POLL);
  354. }
  355.  
  356. /*---------------------------------------------------------------------------*/
  357.  
  358. static void t5_timeout(cp)
  359. struct ax25_cb *cp;
  360. {
  361.   try_send(cp, 1);
  362. }
  363.  
  364. /*---------------------------------------------------------------------------*/
  365.  
  366. static struct ax25_cb *create_axcb(prototype)
  367. struct ax25_cb *prototype;
  368. {
  369.   struct ax25_cb *cp;
  370.  
  371.   if (prototype) {
  372.     cp = (struct ax25_cb *) malloc(sizeof(struct ax25_cb ));
  373.     *cp = *prototype;
  374.   } else
  375.     cp = (struct ax25_cb *) calloc(1, sizeof(struct ax25_cb ));
  376.   cp->cwind = 1;
  377.   cp->timer_t1.func = (void (*)()) t1_timeout;
  378.   cp->timer_t1.arg = cp;
  379.   cp->timer_t2.func = (void (*)()) t2_timeout;
  380.   cp->timer_t2.arg = cp;
  381.   cp->timer_t3.func = (void (*)()) t3_timeout;
  382.   cp->timer_t3.arg = cp;
  383.   cp->timer_t4.func = (void (*)()) t4_timeout;
  384.   cp->timer_t4.arg = cp;
  385.   cp->timer_t5.func = (void (*)()) t5_timeout;
  386.   cp->timer_t5.arg = cp;
  387.   cp->next = axcb_head;
  388.   return axcb_head = cp;
  389. }
  390.  
  391. /*---------------------------------------------------------------------------*/
  392.  
  393. static void build_path(cp, ifp, hdr, reverse)
  394. struct ax25_cb *cp;
  395. struct iface *ifp;
  396. struct ax25 *hdr;
  397. int  reverse;
  398. {
  399.  
  400.   char  *dest;
  401.   int  d;
  402.   int  i;
  403.   struct ax_route *rp;
  404.  
  405.   if (reverse) {
  406.  
  407.     /*** copy hdr into control block ***/
  408.  
  409.     addrcp(cp->hdr.dest, hdr->source);
  410.     addrcp(cp->hdr.source, hdr->dest);
  411.     for (i = 0; i < hdr->ndigis; i++)
  412.       addrcp(cp->hdr.digis[i], hdr->digis[hdr->ndigis-1-i]);
  413.     cp->hdr.ndigis = hdr->ndigis;
  414.  
  415.     /*** find my last address ***/
  416.  
  417.     cp->hdr.nextdigi = 0;
  418.     for (i = 0; i < cp->hdr.ndigis; i++)
  419.       if (ismyax25addr(cp->hdr.digis[i])) cp->hdr.nextdigi = i + 1;
  420.  
  421.     cp->ifp = ifp;
  422.  
  423.   } else {
  424.  
  425.     /*** copy hdr into control block ***/
  426.  
  427.     cp->hdr = *hdr;
  428.  
  429.     /*** find my last address ***/
  430.  
  431.     cp->hdr.nextdigi = 0;
  432.     for (i = 0; i < cp->hdr.ndigis; i++)
  433.       if (ismyax25addr(cp->hdr.digis[i])) cp->hdr.nextdigi = i + 1;
  434.  
  435.     /*** remove all digipeaters before me ***/
  436.  
  437.     d = cp->hdr.nextdigi - 1;
  438.     if (d > 0) {
  439.       for (i = d; i < cp->hdr.ndigis; i++)
  440.     addrcp(cp->hdr.digis[i-d], cp->hdr.digis[i]);
  441.       cp->hdr.ndigis -= d;
  442.       cp->hdr.nextdigi = 1;
  443.     }
  444.  
  445.     /*** add necessary digipeaters and find interface ***/
  446.  
  447.     dest = cp->hdr.nextdigi < cp->hdr.ndigis ? cp->hdr.digis[cp->hdr.nextdigi] : cp->hdr.dest;
  448.     for (rp = ax_routeptr(dest, 0); rp; rp = rp->digi) {
  449.       if (rp->digi && cp->hdr.ndigis < MAXDIGIS) {
  450.     for (i = cp->hdr.ndigis - 1; i >= cp->hdr.nextdigi; i--)
  451.       addrcp(cp->hdr.digis[i+1], cp->hdr.digis[i]);
  452.     cp->hdr.ndigis++;
  453.     addrcp(cp->hdr.digis[cp->hdr.nextdigi], rp->digi->call);
  454.       }
  455.       cp->ifp = rp->ifp;
  456.     }
  457.     if (!cp->ifp) cp->ifp = axroute_default_ifp;
  458.  
  459.     /*** replace my address with hwaddr of interface ***/
  460.  
  461.     addrcp(cp->hdr.nextdigi ? cp->hdr.digis[0] : cp->hdr.source,
  462.        cp->ifp ? cp->ifp->hwaddr : Mycall);
  463.  
  464.   }
  465.  
  466.   cp->srtt = (ax_t1init * (1 + 2 * (cp->hdr.ndigis - cp->hdr.nextdigi))) / 2;
  467.   cp->mdev = cp->srtt / 2;
  468.   reset_t1(cp);
  469. }
  470.  
  471. /*---------------------------------------------------------------------------*/
  472.  
  473. static int  put_reseq(cp, bp, ns)
  474. struct ax25_cb *cp;
  475. struct mbuf *bp;
  476. int  ns;
  477. {
  478.  
  479.   char  *p;
  480.   int  cnt, sum;
  481.   struct axreseq *rp;
  482.   struct mbuf *tp;
  483.  
  484.   if (next_seq(ns) == cp->vr) return 0;
  485.   rp = &cp->reseq[ns];
  486.   if (rp->bp) return 0;
  487.   for (sum = 0, tp = bp; tp; tp = tp->next) {
  488.     cnt = tp->cnt;
  489.     p = tp->data;
  490.     while (cnt--) sum += uchar(*p++);
  491.   }
  492.   if (ns != cp->vr && sum == rp->sum) return 0;
  493.   rp->bp = bp;
  494.   rp->sum = sum;
  495.   return 1;
  496. }
  497.  
  498. /*---------------------------------------------------------------------------*/
  499.  
  500. int  lapb_input(iface, hdr, bp)
  501. struct iface *iface;
  502. struct ax25 *hdr;
  503. struct mbuf *bp;
  504. {
  505.  
  506.   int  cmdrsp;
  507.   int  control;
  508.   int  for_me;
  509.   int  nr;
  510.   int  ns;
  511.   int  pid;
  512.   int  type;
  513.   struct ax25_cb *cp;
  514.   struct ax25_cb *cpp;
  515.  
  516.   if (!bp) return (-1);
  517.   control = uchar(*bp->data);
  518.   type = ftype(control);
  519.   for_me = (ismyax25addr(hdr->dest) != NULLIF);
  520.  
  521.   if (!for_me && (type == UI || addreq(hdr->source, hdr->dest))) {
  522.     struct mbuf *hbp;
  523.     if (!(hbp = htonax25(hdr, bp))) {
  524.       free_p(bp);
  525.       return (-1);
  526.     }
  527.     axroute(NULLAXCB, hbp);
  528.     return 0;
  529.   }
  530.  
  531.   PULLCHAR(&bp);
  532.   if (bp) pid = uchar(*bp->data);
  533.  
  534.   switch (hdr->cmdrsp) {
  535.   case LAPB_COMMAND:
  536.     cmdrsp = DST_C | (control & PF);
  537.     break;
  538.   case LAPB_RESPONSE:
  539.     cmdrsp = SRC_C | (control & PF);
  540.     break;
  541.   default:
  542.     cmdrsp = VERS1;
  543.     break;
  544.   }
  545.  
  546.   for (cp = axcb_head; cp; cp = cp->next)
  547.     if (addreq(hdr->source, cp->hdr.dest) && addreq(hdr->dest, cp->hdr.source)) break;
  548.   if (!cp) {
  549.     if (for_me && netrom_server_axcb && isnetrom(hdr->source))
  550.       cp = create_axcb(netrom_server_axcb);
  551.     else if (for_me && axcb_server)
  552.       cp = create_axcb(axcb_server);
  553.     else
  554.       cp = create_axcb(NULLAXCB);
  555.     build_path(cp, iface, hdr, 1);
  556.     if (!for_me) {
  557.       cp->peer = cpp = create_axcb(NULLAXCB);
  558.       cpp->peer = cp;
  559.       build_path(cpp, NULLIF, hdr, 0);
  560.     } else
  561.       cpp = NULLAXCB;
  562.   } else
  563.     cpp = cp->peer;
  564.  
  565.   if (type == SABM) {
  566.     int  i;
  567.     build_path(cp, iface, hdr, 1);
  568.     if (cp->unack)
  569.       start_timer(&cp->timer_t1);
  570.     else
  571.       stop_timer(&cp->timer_t1);
  572.     stop_timer(&cp->timer_t2);
  573.     stop_timer(&cp->timer_t4);
  574.     cp->polling = 0;
  575.     cp->rnrsent = 0;
  576.     cp->rejsent = 0;
  577.     cp->remote_busy = 0;
  578.     cp->vr = 0;
  579.     cp->vs = cp->unack;
  580.     cp->retry = 0;
  581.     for (i = 0; i < 8; i++)
  582.       if (cp->reseq[i].bp) {
  583.     free_p(cp->reseq[i].bp);
  584.     cp->reseq[i].bp = 0;
  585.       }
  586.   }
  587.  
  588.   if (cp->mode == STREAM && type == I && pid != PID_NO_L3) {
  589.     cp->mode = DGRAM;
  590.     if (cpp) cpp->mode = DGRAM;
  591.   }
  592.  
  593.   set_timer(&cp->timer_t3, ax_t3init);
  594.   start_timer(&cp->timer_t3);
  595.  
  596.   switch (cp->state) {
  597.  
  598.   case DISCONNECTED:
  599.     if (for_me) {
  600.       if (type == SABM && cmdrsp != VERS1 && cp->r_upcall) {
  601.     send_packet(cp, UA, (cmdrsp == POLL) ? FINAL : RESP, NULLBUF);
  602.     setaxstate(cp, CONNECTED);
  603.       } else {
  604.     if (cmdrsp != RESP && cmdrsp != FINAL)
  605.       send_packet(cp, DM, (cmdrsp == POLL) ? FINAL : RESP, NULLBUF);
  606.     del_ax(cp);
  607.       }
  608.     } else {
  609.       if (type == SABM && cmdrsp != VERS1 && cpp->state == DISCONNECTED) {
  610.     setaxstate(cpp, CONNECTING);
  611.       } else if (type == SABM && cmdrsp != VERS1 && cpp->state == CONNECTING) {
  612.     build_path(cpp, NULLIF, hdr, 0);
  613.     send_packet(cpp, SABM, POLL, NULLBUF);
  614.       } else {
  615.     if (cmdrsp != RESP && cmdrsp != FINAL)
  616.       send_packet(cp, DM, (cmdrsp == POLL) ? FINAL : RESP, NULLBUF);
  617.     if (cpp->state == DISCONNECTED) {
  618.       del_ax(cpp);
  619.       del_ax(cp);
  620.     }
  621.       }
  622.     }
  623.     break;
  624.  
  625.   case CONNECTING:
  626.     switch (type) {
  627.     case I:
  628.     case RR:
  629.     case RNR:
  630.     case REJ:
  631.       break;
  632.     case SABM:
  633.       if (cmdrsp != VERS1) {
  634.     send_packet(cp, UA, (cmdrsp == POLL) ? FINAL : RESP, NULLBUF);
  635.     setaxstate(cp, CONNECTED);
  636.       }
  637.       break;
  638.     case UA:
  639.       if (cmdrsp != VERS1) {
  640.     setaxstate(cp, CONNECTED);
  641.       } else {
  642.     if (cpp && cpp->state == DISCONNECTED)
  643.       send_packet(cpp, DM, FINAL, NULLBUF);
  644.     cp->reason = RESET;
  645.     setaxstate(cp, DISCONNECTING);
  646.       }
  647.       break;
  648.     case DISC:
  649.       send_packet(cp, DM, (cmdrsp == POLL) ? FINAL : RESP, NULLBUF);
  650.     case DM:
  651.     case FRMR:
  652.       if (cpp && cpp->state == DISCONNECTED)
  653.     send_packet(cpp, DM, FINAL, NULLBUF);
  654.       cp->reason = RESET;
  655.       setaxstate(cp, DISCONNECTED);
  656.       break;
  657.     }
  658.     break;
  659.  
  660.   case CONNECTED:
  661.     switch (type) {
  662.     case I:
  663.     case RR:
  664.     case RNR:
  665.     case REJ:
  666.       stop_timer(&cp->timer_t1);
  667.       nr = control >> 5;
  668.       if (((cp->vs - nr) & 7) < cp->unack) {
  669.     if (!cp->polling) {
  670.       cp->retry = 0;
  671.       if (cp->sndtime[(nr-1)&7]) {
  672.         int32 rtt = msclock() - cp->sndtime[(nr-1)&7];
  673.         int32 abserr = (rtt > cp->srtt) ? rtt - cp->srtt : cp->srtt - rtt;
  674.         cp->srtt = ((AGAIN - 1) * cp->srtt + rtt + (AGAIN / 2)) / AGAIN;
  675.         cp->mdev = ((DGAIN - 1) * cp->mdev + abserr + (DGAIN / 2)) / DGAIN;
  676.         reset_t1(cp);
  677.         if (cp->cwind < ax_maxframe) {
  678.           cp->mdev += ((cp->srtt / cp->cwind) / 2);
  679.           cp->cwind++;
  680.         }
  681.       }
  682.     }
  683.     while (((cp->vs - nr) & 7) < cp->unack) {
  684.       cp->resndq = free_p(cp->resndq);
  685.       cp->unack--;
  686.     }
  687.     if (cpp && cpp->rnrsent && !busy(cpp)) send_ack(cpp, RESP);
  688.       }
  689.       if (type == I) {
  690.     if (for_me &&
  691.         pid == PID_NETROM &&
  692.         cp->r_upcall != netrom_server_axcb->r_upcall) {
  693.       new_neighbor(hdr->source);
  694.       setaxstate(cp, DISCONNECTING);
  695.       free_p(bp);
  696.       return 0;
  697.     }
  698.     ns = (control >> 1) & 7;
  699.     if (!bp) bp = alloc_mbuf(0);
  700.     if (put_reseq(cp, bp, ns))
  701.       while (bp = cp->reseq[cp->vr].bp) {
  702.         cp->reseq[cp->vr].bp = 0;
  703.         cp->vr = next_seq(cp->vr);
  704.         cp->rejsent = 0;
  705.         if (cp->mode == STREAM) PULLCHAR(&bp);
  706.         if (for_me) {
  707.           cp->rcvcnt += len_p(bp);
  708.           if (cp->mode == STREAM)
  709.         append(&cp->rcvq, bp);
  710.           else
  711.         enqueue(&cp->rcvq, bp);
  712.         } else
  713.           send_ax(cpp, bp);
  714.       }
  715.     if (cmdrsp == POLL)
  716.       send_ack(cp, FINAL);
  717.     else {
  718.       set_timer(&cp->timer_t2, ax_t2init);
  719.       start_timer(&cp->timer_t2);
  720.     }
  721.     if (cp->r_upcall && cp->rcvcnt) (*cp->r_upcall)(cp, cp->rcvcnt);
  722.       } else {
  723.     if (cmdrsp == POLL) send_ack(cp, FINAL);
  724.     if (cp->polling && cmdrsp == FINAL) cp->retry = cp->polling = 0;
  725.     if (type == RNR) {
  726.       if (!cp->remote_busy) cp->remote_busy = msclock();
  727.       set_timer(&cp->timer_t4, ax_t4init);
  728.       start_timer(&cp->timer_t4);
  729.       cp->cwind = 1;
  730.     } else {
  731.       cp->remote_busy = 0;
  732.       stop_timer(&cp->timer_t4);
  733.       if (cp->unack && type == REJ) {
  734.         int  old_vs;
  735.         struct mbuf *bp1;
  736.         old_vs = cp->vs;
  737.         cp->vs = (cp->vs - cp->unack) & 7;
  738.         cp->sndtime[cp->vs] = 0;
  739.         dup_p(&bp1, cp->resndq, 0, MAXINT16);
  740.         send_packet(cp, I, CMD, bp1);
  741.         cp->vs = old_vs;
  742.         cp->cwind = 1;
  743.       } else if (cp->unack && cmdrsp == FINAL) {
  744.         struct mbuf *bp1, *qp;
  745.         cp->vs = (cp->vs - cp->unack) & 7;
  746.         for (qp = cp->resndq; qp; qp = qp->anext) {
  747.           cp->sndtime[cp->vs] = 0;
  748.           dup_p(&bp1, qp, 0, MAXINT16);
  749.           send_packet(cp, I, CMD, bp1);
  750.         }
  751.       }
  752.     }
  753.       }
  754.       try_send(cp, 1);
  755.       if (cp->polling || cp->unack && !cp->remote_busy)
  756.     start_timer(&cp->timer_t1);
  757.       if (cp->closed && !cp->sndq && !cp->unack ||
  758.       cp->remote_busy && msclock() - cp->remote_busy > 900000L)
  759.     setaxstate(cp, DISCONNECTING);
  760.       break;
  761.     case SABM:
  762.       send_packet(cp, UA, (cmdrsp == POLL) ? FINAL : RESP, NULLBUF);
  763.       try_send(cp, 1);
  764.       break;
  765.     case DISC:
  766.       send_packet(cp, DM, (cmdrsp == POLL) ? FINAL : RESP, NULLBUF);
  767.     case DM:
  768.       setaxstate(cp, DISCONNECTED);
  769.       break;
  770.     case UA:
  771.       cp->remote_busy = 0;
  772.       stop_timer(&cp->timer_t4);
  773.       if (cp->unack) start_timer(&cp->timer_t1);
  774.       try_send(cp, 1);
  775.       break;
  776.     case FRMR:
  777.       setaxstate(cp, DISCONNECTING);
  778.       break;
  779.     }
  780.     break;
  781.  
  782.   case DISCONNECTING:
  783.     switch (type) {
  784.     case I:
  785.     case RR:
  786.     case RNR:
  787.     case REJ:
  788.     case SABM:
  789.       if (cmdrsp != RESP && cmdrsp != FINAL)
  790.     send_packet(cp, DM, (cmdrsp == POLL) ? FINAL : RESP, NULLBUF);
  791.       break;
  792.     case DISC:
  793.       send_packet(cp, DM, (cmdrsp == POLL) ? FINAL : RESP, NULLBUF);
  794.     case DM:
  795.     case UA:
  796.     case FRMR:
  797.       setaxstate(cp, DISCONNECTED);
  798.       break;
  799.     }
  800.     break;
  801.   }
  802.  
  803.   free_p(bp);
  804.   return 0;
  805. }
  806.  
  807. /*---------------------------------------------------------------------------*/
  808. /******************************* AX25 Commands *******************************/
  809. /*---------------------------------------------------------------------------*/
  810.  
  811. /* Control AX.25 digipeating */
  812.  
  813. static int  dodigipeat(argc, argv, p)
  814. int  argc;
  815. char  *argv[];
  816. void *p;
  817. {
  818.   return setintrc(&Digipeat, "Digipeat", argc, argv, 0, 2);
  819. }
  820.  
  821. /*---------------------------------------------------------------------------*/
  822.  
  823. /* Force a retransmission */
  824.  
  825. static int  doaxkick(argc, argv, p)
  826. int  argc;
  827. char  *argv[];
  828. void *p;
  829. {
  830.   struct ax25_cb *axp;
  831.  
  832.   axp = (struct ax25_cb *) ltop(htol(argv[1]));
  833.   if (!valid_ax(axp)) {
  834.     tprintf(Notval);
  835.     return 1;
  836.   }
  837.   kick_ax(axp);
  838.   return 0;
  839. }
  840.  
  841. /*---------------------------------------------------------------------------*/
  842.  
  843. /* Set maximum number of frames that will be allowed in flight */
  844.  
  845. static int  domaxframe(argc, argv, p)
  846. int  argc;
  847. char  *argv[];
  848. void *p;
  849. {
  850.   return setintrc(&ax_maxframe, "Maxframe", argc, argv, 1, 7);
  851. }
  852.  
  853. /*---------------------------------------------------------------------------*/
  854.  
  855. /* Display or change our AX.25 address */
  856.  
  857. static int  domycall(argc, argv, p)
  858. int  argc;
  859. char  *argv[];
  860. void *p;
  861. {
  862.   char  buf[15];
  863.  
  864.   if (argc < 2) {
  865.     pax25(buf, Mycall);
  866.     printf("Mycall %s\n", buf);
  867.   } else {
  868.     if (setcall(Mycall, argv[1]) == -1) return 1;
  869.     Mycall[ALEN] |= E;
  870.   }
  871.   return 0;
  872. }
  873.  
  874. /*---------------------------------------------------------------------------*/
  875.  
  876. /* Set maximum length of I-frame data field */
  877.  
  878. static int  dopaclen(argc, argv, p)
  879. int  argc;
  880. char  *argv[];
  881. void *p;
  882. {
  883.   return setintrc(&ax_paclen, "Paclen", argc, argv, 1, MAXINT16);
  884. }
  885.  
  886. /*---------------------------------------------------------------------------*/
  887.  
  888. /* Set size of I-frame above which polls will be sent after a timeout */
  889.  
  890. static int  dopthresh(argc, argv, p)
  891. int  argc;
  892. char  *argv[];
  893. void *p;
  894. {
  895.   return setintrc(&ax_pthresh, "Pthresh", argc, argv, 0, MAXINT16);
  896. }
  897.  
  898. /*---------------------------------------------------------------------------*/
  899.  
  900. /* Eliminate a AX25 connection */
  901.  
  902. static int  doaxreset(argc, argv, p)
  903. int  argc;
  904. char  *argv[];
  905. void *p;
  906. {
  907.   struct ax25_cb *cp;
  908.  
  909.   cp = (struct ax25_cb *) htol(argv[1]);
  910.   if (!valid_ax(cp)) {
  911.     printf(Notval);
  912.     return 1;
  913.   }
  914.   reset_ax(cp);
  915.   return 0;
  916. }
  917.  
  918. /*---------------------------------------------------------------------------*/
  919.  
  920. /* Set retry limit count */
  921.  
  922. static int  doretry(argc, argv, p)
  923. int  argc;
  924. char  *argv[];
  925. void *p;
  926. {
  927.   return setintrc(&ax_retry, "Retry", argc, argv, 0, MAXINT16);
  928. }
  929.  
  930. /*---------------------------------------------------------------------------*/
  931.  
  932. static int  dorouteadd(argc, argv, p)
  933. int  argc;
  934. char  *argv[];
  935. void *p;
  936. {
  937.  
  938.   char  tmp[AXALEN];
  939.   int  i, j, perm;
  940.   struct ax25 hdr;
  941.   struct iface *iface;
  942.  
  943.   argc--;
  944.   argv++;
  945.  
  946.   if (perm = !strcmp(*argv, "permanent")) {
  947.     argc--;
  948.     argv++;
  949.   }
  950.  
  951.   if (!(iface = if_lookup(*argv))) {
  952.     printf("Interface \"%s\" unknown\n", *argv);
  953.     return 1;
  954.   }
  955.   if (iface->output != ax_output) {
  956.     printf("Interface \"%s\" not kiss\n", *argv);
  957.     return 1;
  958.   }
  959.   argc--;
  960.   argv++;
  961.  
  962.   if (argc <= 0) {
  963.     printf("Usage: ax25 route add [permanent] <interface> default|<path>\n");
  964.     return 1;
  965.   }
  966.  
  967.   if (!strcmp(*argv, "default")) {
  968.     axroute_default_ifp = iface;
  969.     return 0;
  970.   }
  971.  
  972.   if (setcall(hdr.source, *argv)) {
  973.     printf("Invalid call \"%s\"\n", *argv);
  974.     return 1;
  975.   }
  976.   argc--;
  977.   argv++;
  978.  
  979.   for (hdr.nextdigi = 0; argc > 0; argc--, argv++)
  980.     if (strncmp("via", *argv, strlen(*argv))) {
  981.       if (hdr.nextdigi >= MAXDIGIS) {
  982.     printf("Too many digipeaters (max %d)\n", MAXDIGIS);
  983.     return 1;
  984.       }
  985.       if (setcall(hdr.digis[hdr.nextdigi++], *argv)) {
  986.     printf("Invalid call \"%s\"\n", *argv);
  987.     return 1;
  988.       }
  989.     }
  990.   for (i = 0, j = hdr.nextdigi - 1; i < j; i++, j--) {
  991.     addrcp(tmp, hdr.digis[i]);
  992.     addrcp(hdr.digis[i], hdr.digis[j]);
  993.     addrcp(hdr.digis[j], tmp);
  994.   }
  995.  
  996.   axroute_add(iface, &hdr, perm);
  997.   return 0;
  998. }
  999.  
  1000. /*---------------------------------------------------------------------------*/
  1001.  
  1002. static void doroutelistentry(rp)
  1003. struct ax_route *rp;
  1004. {
  1005.  
  1006.   char  *cp, buf[1024];
  1007.   int  i, n;
  1008.   int  perm;
  1009.   struct ax_route *rp_stack[20];
  1010.   struct iface *ifp;
  1011.   struct tm *tm;
  1012.  
  1013.   tm = gmtime(&rp->time);
  1014.   pax25(cp = buf, rp->call);
  1015.   perm = rp->perm;
  1016.   for (n = 0; rp; rp = rp->digi) {
  1017.     rp_stack[++n] = rp;
  1018.     ifp = rp->ifp;
  1019.   }
  1020.   for (i = n; i > 1; i--) {
  1021.     strcat(cp, i == n ? " via " : ",");
  1022.     while (*cp) cp++;
  1023.     pax25(cp, rp_stack[i]->call);
  1024.   }
  1025.   printf("%2d-%.3s  %-9s  %c %s\n",
  1026.      tm->tm_mday,
  1027.      "JanFebMarAprMayJunJulAugSepOctNovDec" + 3 * tm->tm_mon,
  1028.      ifp ? ifp->name : "???",
  1029.      perm ? '*' : ' ',
  1030.      buf);
  1031. }
  1032.  
  1033. /*---------------------------------------------------------------------------*/
  1034.  
  1035. static int  doroutelist(argc, argv, p)
  1036. int  argc;
  1037. char  *argv[];
  1038. void *p;
  1039. {
  1040.  
  1041.   char  call[AXALEN];
  1042.   int  i;
  1043.   struct ax_route *rp;
  1044.  
  1045.   puts("Date    Interface  P Path");
  1046.   if (argc < 2) {
  1047.     for (i = 0; i < AXROUTESIZE; i++)
  1048.       for (rp = Ax_routes[i]; rp; rp = rp->next) doroutelistentry(rp);
  1049.     return 0;
  1050.   }
  1051.   argc--;
  1052.   argv++;
  1053.   for (; argc > 0; argc--, argv++)
  1054.     if (setcall(call, *argv) || !(rp = ax_routeptr(call, 0)))
  1055.       printf("*** Not in table *** %s\n", *argv);
  1056.     else
  1057.       doroutelistentry(rp);
  1058.   return 0;
  1059. }
  1060.  
  1061. /*---------------------------------------------------------------------------*/
  1062.  
  1063. static int  doroutestat(argc, argv, p)
  1064. int  argc;
  1065. char  *argv[];
  1066. void *p;
  1067. {
  1068.  
  1069.   int  count[ASY_MAX], total;
  1070.   int  i, dev;
  1071.   struct ax_route *rp, *dp;
  1072.   struct iface *ifp, *ifptable[ASY_MAX];
  1073.  
  1074.   memset(ifptable, 0, sizeof(ifptable));
  1075.   memset(count, 0, sizeof(count));
  1076.   for (ifp = Ifaces; ifp; ifp = ifp->next)
  1077.     if (ifp->output == ax_output) ifptable[ifp->dev] = ifp;
  1078.   for (i = 0; i < AXROUTESIZE; i++)
  1079.     for (rp = Ax_routes[i]; rp; rp = rp->next) {
  1080.       for (dp = rp; dp->digi; dp = dp->digi) ;
  1081.       if (dp->ifp) count[dp->ifp->dev]++;
  1082.     }
  1083.   puts("Interface  Count");
  1084.   total = 0;
  1085.   for (dev = 0; dev < ASY_MAX && ifptable[dev]; dev++) {
  1086.     if (ifptable[dev] == axroute_default_ifp || count[dev])
  1087.       printf("%c %-7s  %5d\n", ifptable[dev] == axroute_default_ifp ? '*' : ' ', ifptable[dev]->name, count[dev]);
  1088.     total += count[dev];
  1089.   }
  1090.   puts("---------  -----");
  1091.   printf("  total    %5d\n", total);
  1092.   return 0;
  1093. }
  1094.  
  1095. /*---------------------------------------------------------------------------*/
  1096.  
  1097. static int  doaxroute(argc, argv, p)
  1098. int  argc;
  1099. char  *argv[];
  1100. void *p;
  1101. {
  1102.  
  1103.   static struct cmds routecmds[] = {
  1104.  
  1105.     "add",  dorouteadd,  0, 3, "ax25 route add [permanent] <interface> default|<path>",
  1106.     "list", doroutelist, 0, 0, NULLCHAR,
  1107.     "stat", doroutestat, 0, 0, NULLCHAR,
  1108.  
  1109.     NULLCHAR, NULLFP,    0, 0, NULLCHAR
  1110.   };
  1111.  
  1112.   axroute_loadfile();
  1113.   if (argc >= 2) return subcmd(routecmds, argc, argv, p);
  1114.   doroutestat(argc, argv, p);
  1115.   return 0;
  1116. }
  1117.  
  1118. /*---------------------------------------------------------------------------*/
  1119.  
  1120. /* Display AX.25 link level control blocks */
  1121.  
  1122. static int  doaxstatus(argc, argv, p)
  1123. int  argc;
  1124. char  *argv[];
  1125. void *p;
  1126. {
  1127.  
  1128.   int  i;
  1129.   struct ax25_cb *cp;
  1130.   struct mbuf *bp;
  1131.  
  1132.   if (argc < 2) {
  1133.     printf("   &AXCB Rcv-Q Unack  Rt  Srtt  State          Remote socket\n");
  1134.     for (cp = axcb_head; cp; cp = cp->next)
  1135.       printf("%8lx %5u%c%3u/%u%c %2d%6lu  %-13s  %s\n",
  1136.          (long) cp,
  1137.          cp->rcvcnt,
  1138.          cp->rnrsent ? '*' : ' ',
  1139.          cp->unack,
  1140.          cp->cwind,
  1141.          cp->remote_busy ? '*' : ' ',
  1142.          cp->retry,
  1143.          cp->srtt,
  1144.          ax25states[cp->state],
  1145.          ax25hdr_to_string(&cp->hdr));
  1146.     if (axcb_server)
  1147.       printf("%8lx                        Listen (S)     *\n",
  1148.          (long) axcb_server);
  1149.   } else {
  1150.     cp = (struct ax25_cb *) htol(argv[1]);
  1151.     if (!valid_ax(cp)) {
  1152.       printf("Not a valid control block address\n");
  1153.       return 1;
  1154.     }
  1155.     printf("Path:         %s\n", ax25hdr_to_string(&cp->hdr));
  1156.     printf("Interface:    %s\n", cp->ifp ? cp->ifp->name : "---");
  1157.     printf("State:        %s\n", (cp == axcb_server) ? "Listen (S)" : ax25states[cp->state]);
  1158.     if (cp->reason)
  1159.       printf("Reason:       %s\n", ax25reasons[cp->reason]);
  1160.     printf("Mode:         %s\n", (cp->mode == STREAM) ? "Stream" : "Dgram");
  1161.     printf("Closed:       %s\n", cp->closed ? "Yes" : "No");
  1162.     printf("Polling:      %s\n", cp->polling ? "Yes" : "No");
  1163.     printf("RNRsent:      %s\n", cp->rnrsent ? "Yes" : "No");
  1164.     printf("REJsent:      %s\n", cp->rejsent ? "Yes" : "No");
  1165.     if (cp->remote_busy)
  1166.       printf("Remote_busy:  %lu ms\n", msclock() - cp->remote_busy);
  1167.     else
  1168.       printf("Remote_busy:  No\n");
  1169.     printf("CWind:        %d\n", cp->cwind);
  1170.     printf("Retry:        %d\n", cp->retry);
  1171.     printf("Srtt:         %ld ms\n", cp->srtt);
  1172.     printf("Mean dev:     %ld ms\n", cp->mdev);
  1173.     tprintf("Timer T1:     ");
  1174.     if (run_timer(&cp->timer_t1))
  1175.       tprintf("%lu", read_timer(&cp->timer_t1));
  1176.     else
  1177.       tprintf("stop");
  1178.     tprintf("/%lu ms\n", dur_timer(&cp->timer_t1));
  1179.     tprintf("Timer T2:     ");
  1180.     if (run_timer(&cp->timer_t2))
  1181.       tprintf("%lu", read_timer(&cp->timer_t2));
  1182.     else
  1183.       tprintf("stop");
  1184.     tprintf("/%lu ms\n", dur_timer(&cp->timer_t2));
  1185.     tprintf("Timer T3:     ");
  1186.     if (run_timer(&cp->timer_t3))
  1187.       tprintf("%lu", read_timer(&cp->timer_t3));
  1188.     else
  1189.       tprintf("stop");
  1190.     tprintf("/%lu ms\n", dur_timer(&cp->timer_t3));
  1191.     tprintf("Timer T4:     ");
  1192.     if (run_timer(&cp->timer_t4))
  1193.       tprintf("%lu", read_timer(&cp->timer_t4));
  1194.     else
  1195.       tprintf("stop");
  1196.     tprintf("/%lu ms\n", dur_timer(&cp->timer_t4));
  1197.     tprintf("Timer T5:     ");
  1198.     if (run_timer(&cp->timer_t5))
  1199.       tprintf("%lu", read_timer(&cp->timer_t5));
  1200.     else
  1201.       tprintf("stop");
  1202.     tprintf("/%lu ms\n", dur_timer(&cp->timer_t5));
  1203.     printf("Rcv queue:    %d\n", cp->rcvcnt);
  1204.     if (cp->reseq[0].bp || cp->reseq[1].bp ||
  1205.     cp->reseq[2].bp || cp->reseq[3].bp ||
  1206.     cp->reseq[4].bp || cp->reseq[5].bp ||
  1207.     cp->reseq[6].bp || cp->reseq[7].bp) {
  1208.       printf("Reassembly queue:\n");
  1209.       for (i = next_seq(cp->vr); i != cp->vr; i = next_seq(i))
  1210.     if (cp->reseq[i].bp)
  1211.       printf("              Seq %3d: %3d bytes\n",
  1212.          i, len_p(cp->reseq[i].bp));
  1213.     }
  1214.     printf("Snd queue:    %d\n", len_p(cp->sndq));
  1215.     if (cp->resndq) {
  1216.       printf("Resend queue:\n");
  1217.       for (i = 0, bp = cp->resndq; bp; i++, bp = bp->anext)
  1218.     printf("              Seq %3d: %3d bytes\n",
  1219.            (cp->vs - cp->unack + i) & 7, len_p(bp));
  1220.     }
  1221.   }
  1222.   return 0;
  1223. }
  1224.  
  1225. /*---------------------------------------------------------------------------*/
  1226.  
  1227. /* Set retransmission timer */
  1228.  
  1229. static int  dot1(argc, argv, p)
  1230. int  argc;
  1231. char  *argv[];
  1232. void *p;
  1233. {
  1234.   return setintrc(&ax_t1init, "T1 (ms)", argc, argv, 1, 0x7fffffff);
  1235. }
  1236.  
  1237. /*---------------------------------------------------------------------------*/
  1238.  
  1239. /* Set acknowledgement delay timer */
  1240.  
  1241. static int  dot2(argc, argv, p)
  1242. int  argc;
  1243. char  *argv[];
  1244. void *p;
  1245. {
  1246.   return setintrc(&ax_t2init, "T2 (ms)", argc, argv, 1, 0x7fffffff);
  1247. }
  1248.  
  1249. /*---------------------------------------------------------------------------*/
  1250.  
  1251. /* Set no-activity timer */
  1252.  
  1253. static int  dot3(argc, argv, p)
  1254. int  argc;
  1255. char  *argv[];
  1256. void *p;
  1257. {
  1258.   return setintrc(&ax_t3init, "T3 (ms)", argc, argv, 0, 0x7fffffff);
  1259. }
  1260.  
  1261. /*---------------------------------------------------------------------------*/
  1262.  
  1263. /* Set busy timer */
  1264.  
  1265. static int  dot4(argc, argv, p)
  1266. int  argc;
  1267. char  *argv[];
  1268. void *p;
  1269. {
  1270.   return setintrc(&ax_t4init, "T4 (ms)", argc, argv, 1, 0x7fffffff);
  1271. }
  1272.  
  1273. /*---------------------------------------------------------------------------*/
  1274.  
  1275. /* Set packet assembly timer */
  1276.  
  1277. static int  dot5(argc, argv, p)
  1278. int  argc;
  1279. char  *argv[];
  1280. void *p;
  1281. {
  1282.   return setintrc(&ax_t5init, "T5 (ms)", argc, argv, 1, 0x7fffffff);
  1283. }
  1284.  
  1285. /*---------------------------------------------------------------------------*/
  1286.  
  1287. /* Set high water mark on receive queue that triggers RNR */
  1288.  
  1289. static int  doaxwindow(argc, argv, p)
  1290. int  argc;
  1291. char  *argv[];
  1292. void *p;
  1293. {
  1294.   return setintrc(&ax_window, "Window", argc, argv, 1, MAXINT16);
  1295. }
  1296.  
  1297. /*---------------------------------------------------------------------------*/
  1298.  
  1299. /* Multiplexer for top-level ax25 command */
  1300.  
  1301. int  doax25(argc, argv, p)
  1302. int  argc;
  1303. char  *argv[];
  1304. void *p;
  1305. {
  1306.  
  1307.   static struct cmds axcmds[] = {
  1308.  
  1309.     "digipeat", dodigipeat, 0, 0, NULLCHAR,
  1310.     "kick",     doaxkick,   0, 2, "ax25 kick <axcb>",
  1311.     "maxframe", domaxframe, 0, 0, NULLCHAR,
  1312.     "mycall",   domycall,   0, 0, NULLCHAR,
  1313.     "paclen",   dopaclen,   0, 0, NULLCHAR,
  1314.     "pthresh",  dopthresh,  0, 0, NULLCHAR,
  1315.     "reset",    doaxreset,  0, 2, "ax25 reset <axcb>",
  1316.     "retry",    doretry,    0, 0, NULLCHAR,
  1317.     "route",    doaxroute,  0, 0, NULLCHAR,
  1318.     "status",   doaxstatus, 0, 0, NULLCHAR,
  1319.     "t1",       dot1,       0, 0, NULLCHAR,
  1320.     "t2",       dot2,       0, 0, NULLCHAR,
  1321.     "t3",       dot3,       0, 0, NULLCHAR,
  1322.     "t4",       dot4,       0, 0, NULLCHAR,
  1323.     "t5",       dot5,       0, 0, NULLCHAR,
  1324.     "window",   doaxwindow, 0, 0, NULLCHAR,
  1325.  
  1326.     NULLCHAR,   NULLFP,     0, 0, NULLCHAR
  1327.   };
  1328.  
  1329.   return subcmd(axcmds, argc, argv, p);
  1330. }
  1331.  
  1332. /*---------------------------------------------------------------------------*/
  1333. /***************************** User Calls to AX25 ****************************/
  1334. /*---------------------------------------------------------------------------*/
  1335.  
  1336. struct ax25_cb *open_ax(path, mode, r_upcall, t_upcall, s_upcall, user)
  1337. char  *path;
  1338. int  mode;
  1339. void (*r_upcall) __ARGS((struct ax25_cb *p, int cnt));
  1340. void (*t_upcall) __ARGS((struct ax25_cb *p, int cnt));
  1341. void (*s_upcall) __ARGS((struct ax25_cb *p, int oldstate, int newstate));
  1342. char  *user;
  1343. {
  1344.  
  1345.   char  *ap;
  1346.   struct ax25 hdr;
  1347.   struct ax25_cb *cp;
  1348.  
  1349.   switch (mode) {
  1350.   case AX_ACTIVE:
  1351.     hdr.ndigis = hdr.nextdigi = 0;
  1352.     ap = path;
  1353.     addrcp(hdr.dest, ap);
  1354.     ap += AXALEN;
  1355.     addrcp(hdr.source, ap);
  1356.     ap += AXALEN;
  1357.     while (!(ap[-1] & E)) {
  1358.       addrcp(hdr.digis[hdr.ndigis++], ap);
  1359.       ap += AXALEN;
  1360.     }
  1361.     for (cp = axcb_head; cp; cp = cp->next)
  1362.       if (!cp->peer && addreq(hdr.dest, cp->hdr.dest)) {
  1363.     Net_error = CON_EXISTS;
  1364.     return NULLAXCB;
  1365.       }
  1366.     if (!(cp = create_axcb(NULLAXCB))) {
  1367.       Net_error = NO_MEM;
  1368.       return NULLAXCB;
  1369.     }
  1370.     build_path(cp, NULLIF, &hdr, 0);
  1371.     cp->r_upcall = r_upcall;
  1372.     cp->t_upcall = t_upcall;
  1373.     cp->s_upcall = s_upcall;
  1374.     cp->user = user;
  1375.     setaxstate(cp, CONNECTING);
  1376.     return cp;
  1377.   case AX_SERVER:
  1378.     if (!(cp = (struct ax25_cb *) calloc(1, sizeof(struct ax25_cb )))) {
  1379.       Net_error = NO_MEM;
  1380.       return NULLAXCB;
  1381.     }
  1382.     cp->r_upcall = r_upcall;
  1383.     cp->t_upcall = t_upcall;
  1384.     cp->s_upcall = s_upcall;
  1385.     cp->user = user;
  1386.     return cp;
  1387.   default:
  1388.     Net_error = INVALID;
  1389.     return NULLAXCB;
  1390.   }
  1391. }
  1392.  
  1393. /*---------------------------------------------------------------------------*/
  1394.  
  1395. int  send_ax(cp, bp)
  1396. struct ax25_cb *cp;
  1397. struct mbuf *bp;
  1398. {
  1399.   int cnt;
  1400.  
  1401.   if (!(cp && bp)) {
  1402.     free_p(bp);
  1403.     Net_error = INVALID;
  1404.     return (-1);
  1405.   }
  1406.   switch (cp->state) {
  1407.   case DISCONNECTED:
  1408.     free_p(bp);
  1409.     Net_error = NO_CONN;
  1410.     return (-1);
  1411.   case CONNECTING:
  1412.   case CONNECTED:
  1413.     if (!cp->closed) {
  1414.       if (cnt = len_p(bp)) {
  1415.     if (cp->mode == STREAM)
  1416.       append(&cp->sndq, bp);
  1417.     else
  1418.       enqueue(&cp->sndq, bp);
  1419.     cp->sndqtime = msclock();
  1420.     try_send(cp, 0);
  1421.       }
  1422.       return cnt;
  1423.     }
  1424.   case DISCONNECTING:
  1425.     free_p(bp);
  1426.     Net_error = CON_CLOS;
  1427.     return (-1);
  1428.   }
  1429.   return (-1);
  1430. }
  1431.  
  1432. /*---------------------------------------------------------------------------*/
  1433.  
  1434. int  space_ax(cp)
  1435. struct ax25_cb *cp;
  1436. {
  1437.   int  cnt;
  1438.  
  1439.   if (!cp) {
  1440.     Net_error = INVALID;
  1441.     return (-1);
  1442.   }
  1443.   switch (cp->state) {
  1444.   case DISCONNECTED:
  1445.     Net_error = NO_CONN;
  1446.     return (-1);
  1447.   case CONNECTING:
  1448.   case CONNECTED:
  1449.     if (!cp->closed) {
  1450.       cnt = (cp->cwind - cp->unack) * ax_paclen - len_p(cp->sndq);
  1451.       return (cnt > 0) ? cnt : 0;
  1452.     }
  1453.   case DISCONNECTING:
  1454.     Net_error = CON_CLOS;
  1455.     return (-1);
  1456.   }
  1457.   return (-1);
  1458. }
  1459.  
  1460. /*---------------------------------------------------------------------------*/
  1461.  
  1462. int  recv_ax(cp, bpp, cnt)
  1463. struct ax25_cb *cp;
  1464. struct mbuf **bpp;
  1465. int cnt;
  1466. {
  1467.   if (!(cp && bpp)) {
  1468.     Net_error = INVALID;
  1469.     return (-1);
  1470.   }
  1471.   if (cp->rcvcnt) {
  1472.     if (cp->mode == DGRAM || !cnt || cp->rcvcnt <= cnt) {
  1473.       *bpp = dequeue(&cp->rcvq);
  1474.       cnt = len_p(*bpp);
  1475.     } else {
  1476.       if (!(*bpp = alloc_mbuf(cnt))) {
  1477.     Net_error = NO_MEM;
  1478.     return (-1);
  1479.       }
  1480.       pullup(&cp->rcvq, (*bpp)->data, cnt);
  1481.       (*bpp)->cnt = cnt;
  1482.     }
  1483.     cp->rcvcnt -= cnt;
  1484.     if (cp->rnrsent && !busy(cp)) send_ack(cp, RESP);
  1485.     return cnt;
  1486.   }
  1487.   switch (cp->state) {
  1488.   case CONNECTING:
  1489.   case CONNECTED:
  1490.     *bpp = NULLBUF;
  1491.     Net_error = WOULDBLK;
  1492.     return (-1);
  1493.   case DISCONNECTED:
  1494.   case DISCONNECTING:
  1495.     *bpp = NULLBUF;
  1496.     return 0;
  1497.   }
  1498.   return (-1);
  1499. }
  1500.  
  1501. /*---------------------------------------------------------------------------*/
  1502.  
  1503. int  close_ax(cp)
  1504. struct ax25_cb *cp;
  1505. {
  1506.   if (!cp) {
  1507.     Net_error = INVALID;
  1508.     return (-1);
  1509.   }
  1510.   if (cp->closed) {
  1511.     Net_error = CON_CLOS;
  1512.     return (-1);
  1513.   }
  1514.   cp->closed = 1;
  1515.   switch (cp->state) {
  1516.   case DISCONNECTED:
  1517.     Net_error = NO_CONN;
  1518.     return (-1);
  1519.   case CONNECTING:
  1520.     setaxstate(cp, DISCONNECTED);
  1521.     return 0;
  1522.   case CONNECTED:
  1523.     if (!cp->sndq && !cp->unack) setaxstate(cp, DISCONNECTING);
  1524.     return 0;
  1525.   case DISCONNECTING:
  1526.     Net_error = CON_CLOS;
  1527.     return (-1);
  1528.   }
  1529.   return (-1);
  1530. }
  1531.  
  1532. /*---------------------------------------------------------------------------*/
  1533.  
  1534. int  reset_ax(cp)
  1535. struct ax25_cb *cp;
  1536. {
  1537.   if (!cp) {
  1538.     Net_error = INVALID;
  1539.     return (-1);
  1540.   }
  1541.   if (cp == axcb_server) {
  1542.     free(axcb_server);
  1543.     axcb_server = NULLAXCB;
  1544.     return 0;
  1545.   }
  1546.   cp->reason = RESET;
  1547.   setaxstate(cp, DISCONNECTED);
  1548.   return 0;
  1549. }
  1550.  
  1551. /*---------------------------------------------------------------------------*/
  1552.  
  1553. int  del_ax(cp)
  1554. struct ax25_cb *cp;
  1555. {
  1556.  
  1557.   int  i;
  1558.   struct ax25_cb *p, *q;
  1559.  
  1560.   for (q = 0, p = axcb_head; p != cp; q = p, p = p->next)
  1561.     if (!p) {
  1562.       Net_error = INVALID;
  1563.       return (-1);
  1564.     }
  1565.   if (q)
  1566.     q->next = p->next;
  1567.   else
  1568.     axcb_head = p->next;
  1569.   stop_timer(&cp->timer_t1);
  1570.   stop_timer(&cp->timer_t2);
  1571.   stop_timer(&cp->timer_t3);
  1572.   stop_timer(&cp->timer_t4);
  1573.   stop_timer(&cp->timer_t5);
  1574.   for (i = 0; i < 8; i++) free_p(cp->reseq[i].bp);
  1575.   free_q(&cp->rcvq);
  1576.   free_q(&cp->sndq);
  1577.   free_q(&cp->resndq);
  1578.   free(cp);
  1579.   return 0;
  1580. }
  1581.  
  1582. /*---------------------------------------------------------------------------*/
  1583.  
  1584. int  valid_ax(cp)
  1585. struct ax25_cb *cp;
  1586. {
  1587.   struct ax25_cb *p;
  1588.  
  1589.   if (!cp) return 0;
  1590.   if (cp == axcb_server) return 1;
  1591.   for (p = axcb_head; p; p = p->next)
  1592.     if (p == cp) return 1;
  1593.   return 0;
  1594. }
  1595.  
  1596. /*---------------------------------------------------------------------------*/
  1597.  
  1598. /* Force a retransmission */
  1599.  
  1600. int  kick_ax(axp)
  1601. struct ax25_cb *axp;
  1602. {
  1603.   if (!valid_ax(axp)) return -1;
  1604.   t1_timeout(axp);
  1605.   return 0;
  1606. }
  1607.  
  1608.